package com.lalilu.lmedia.database

import androidx.room.*
import com.lalilu.lmedia.entity.SongInPlaylist
import kotlinx.coroutines.flow.Flow

@Dao
abstract class SongInPlaylistDao : LinkableDao<SongInPlaylist>() {

    @Insert(entity = SongInPlaylist::class, onConflict = OnConflictStrategy.REPLACE)
    abstract override fun insert(item: SongInPlaylist): Long

    @Insert(entity = SongInPlaylist::class, onConflict = OnConflictStrategy.REPLACE)
    abstract override fun insertAll(items: List<SongInPlaylist>)

    @Delete(entity = SongInPlaylist::class)
    abstract override fun remove(item: SongInPlaylist)

    @Update(entity = SongInPlaylist::class)
    abstract override fun update(item: SongInPlaylist)

    @Transaction
    @Update(entity = SongInPlaylist::class)
    abstract override fun updateAll(items: List<SongInPlaylist>)

    @Query("SELECT * FROM song_in_playlist WHERE s_p_id = :id AND p_id = :classifyId LIMIT 1;")
    abstract override fun getById(id: Long, classifyId: Long?): SongInPlaylist?

    @Query("SELECT * FROM song_in_playlist WHERE nextId = :nextId AND p_id = :classifyId LIMIT 1;")
    abstract override fun getByNextId(nextId: Long, classifyId: Long?): SongInPlaylist?

    @Query("SELECT * FROM song_in_playlist WHERE nextId IS NULL AND p_id = :classifyId LIMIT 1;")
    abstract override fun getLastOne(classifyId: Long?): SongInPlaylist?

    @Query("SELECT * FROM song_in_playlist ORDER BY s_p_id DESC LIMIT 1;")
    abstract override fun getLastOne(): SongInPlaylist?

    @Query("SELECT EXISTS (SELECT 1 FROM song_in_playlist WHERE p_id = :pId AND s_id = :mediaId LIMIT 1);")
    abstract fun checkSongInPlaylistExist(pId: Long, mediaId: String): Boolean

    @Transaction
    override fun checkExist(item: SongInPlaylist): Boolean {
        return checkSongInPlaylistExist(item.playlistId, item.mediaId)
    }

    @Query("SELECT 1 FROM song_in_playlist WHERE p_id = :playlistId AND s_id = :mediaId LIMIT 1;")
    abstract fun isContainItemInPlaylist(mediaId: String, playlistId: Long): Flow<Boolean?>

    @Query("SELECT * FROM song_in_playlist WHERE p_id = :playlistId;")
    abstract fun getSongInPlaylistsByPlaylistId(playlistId: Long): Flow<List<SongInPlaylist>>

    @Query("SELECT * FROM song_in_playlist WHERE p_id = :playlistId;")
    abstract fun getSongInPlaylistsById(playlistId: Long): List<SongInPlaylist>

    @Query("SELECT * FROM song_in_playlist WHERE p_id = :pId AND s_id = :mediaId LIMIT 1;")
    abstract fun getSongInPlaylist(pId: Long, mediaId: String): SongInPlaylist?

    @Transaction
    open fun deleteSongInPlaylists(songInPlaylists: List<SongInPlaylist>) {
        removeItems(songInPlaylists.mapNotNull {
            getSongInPlaylist(
                pId = it.playlistId,
                mediaId = it.mediaId
            )
        })
    }
}